<?php
/**
 * <OXmlElement>
 *  Copyright (C) <2011>  <Omar Teodoro Alegre>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * ********************************************************
 * ********************************************************
 *                    OXmlElement
 * ********************************************************
 * ********************************************************
 * 
 * @version 1.0
 * @created 28-ago-2011 07:07:53 p.m.
 * @author Omar Teodoro Alegre - alegreomarteodoro@yahoo.com.ar 
 *  Corrientes, Argentina.
 */

require_once dirname(__FILE__) . '/OXmlValidator.php';
require_once dirname(__FILE__) . '/OXmlAttribute.php';

class OXmlElement
{
	protected $_child_elements = array();
	protected $_attributes = array();
	protected $_value = '';
	protected $_name = '';
	protected $_parent_element = NULL;

    /** Constructor */
	
	function __construct( $name , $value = NULL, $id = NULL )
	{
            $this->setName($name);
            $this->setValue($value);
            if( $id != NULL )
            	$this->setId($id);
	}

	
	/* Metodos */

	/**
	 * Devuelve una cadena con el elemento en formato xml.
	 */
	public function toString()
	{
                $output = "<{$this->getName()}";
                
                if( $this->verifyAttributes() )
                {
                    foreach ( $this->getAllAttributes() as $attribute )
                    {
                        $output .= ' ' . $attribute->toString();
                    }
                }
                
                $output .= '>';
                
                if( $this->verifyChildElements() )
                {
                    foreach ( $this->getAllChildElements() as $element )
                    {
                        $output .= ' ' . $element->toString();
                    }
                }
                else
                {
                    $output .= $this->getValue();
                }
                
                $output .= "</{$this->getName()}>";
                
                return $output;
	}

	/**
	 * Devuelve la cantidad de atributos que contiene el elemento.
	 */
	public function countAttributes()
	{
		return count($this->getAllAttributes());
	}

	/**
	 * Verifica si el elemento contiene atributos.
	 * @return boolean.
	 */
	public function verifyAttributes()
	{
		if ( $this->countAttributes() > 0 )
                return true;
       	return false;
	}
        
	/**
	 * Verifica si el elemento contiene otros elementos.
	 * @return boolean.
	 */
	public function verifyChildElements()
	{
		if ( $this->countChildElements() > 0 )
			return true;
		return false;
	}

	/**
	 * Devuelve la cantidad de elementos que contiene el elemento.
	 * @return Int - Cantidad de elementos hijos.
	 */
	public function countChildElements()
	{
		return count( $this->getAllChildElements() );
	}

    /**
	 * Agrega atributos al elemento. 
	 * @param OXmlAttribute $attribute
	 * @return boolean - Si pudo agregar el elemento retorna verdadero, en caso contrario falso.
	 */
	public function addAttribute(OXmlAttribute $attribute)
	{
		if( !array_key_exists( $attribute->getName() , $this->getAllAttributes() ) )
		{
			$attribute->setParentElement($this);
			$this->_attributes[$attribute->getName()] = $attribute;
			return true;
		}
		return false;
	}

	/**
	 * Elimina todos los atributos que contiene el elemento.
	 */
	public function deleteAllAttributes()
	{
		unset($this->_attributes);
	}

	/**
	 * Elimina un atributo.
	 * @param String attribute_name - Nombre del atributo que se desea eliminar.
	 * @return boolean.
	 */
	public function deleteAttribute($attribute_name)
	{
		$attribute_name = OXmlValidator::checkName($attribute_name);
		
		if( array_key_exists( $attribute_name , $this->getAllAttributes() ) )
		{
			unset( $this->_attributes[$attribute_name] );
			return true;
		}
		return false;
	}

	/**
	 * Devuelve todos los atributos que el elemento contiene actualmente.
	 */
	public function getAllAttributes()
	{
		return $this->_attributes;
	}

	/**
	 * Devuelve un atributo.
	 * @param String attribute_name - Nombre del atributo.
	 * @return OXmlAttribute - Si encuentra el atributo devuelve un objeto del tipo OXmlAttribute en caso contrario Falso.
	 */
	public function getAttribute($attribute_name)
	{
		if( array_key_exists( $attribute_name , $this->getAllAttributes() ) )
		{
			return $this->_attributes[$attribute_name];
		}
		return false;
	}
	
	/**
	 * Agrega un elemento hijo al elemento actual.
	 * @param OXmlElement $child_element - Elemento.
	 */
	public function addChildElement( OXmlElement $child_element )
	{
		$child_element->setParentElement($this);
		$this->_child_elements[] = $child_element;
	}
        
	/**
	 * Devuelve todos los elementos hijos.
	 * @return OXmlElement Array - Array de elementos hijos.
	 */
	public function getAllChildElements()
	{
		return $this->_child_elements;
	}
	
	/**
	 * Devuelve el primer elemento hijo.
	 * @return OXmlElement - Primer elemento hijo.
	 */
	public function getFirstChildElement()
	{
		return $this->_child_elements[0];
	}
	
	/**
	 * Devuelve el ultimo elemento hijo.
	 * @return OXmlElement - Ultimo elemento hijo.
	 */
	public function getLastChildElement()
	{
		$lenght = $this->countChildElements();
		return $this->_child_elements[ $lenght - 1 ];
	}

	/** Setters and Getters */
        
	/**
	 * Especifica el nombre del elemento.
	 * @param String name - Nombre del elemento.
	 */
	public function setName($name)
	{
		$this->_name = OXmlValidator::checkName( $name ); 
	}
    
	/**
	 * Devuelve el nombre del elemento.
	 * @return String - Nombre del elemento.
	 */
	public function getName()
	{
		return $this->_name;
	}

	/**
	 * Define el valor del elemento actual.
	 * @param Var value
	 */
	public function setValue($value)
	{
		$this->_value = OXmlValidator::checkValue( $value ); 
	}
	
    /**
     * Devuelve el valor el elemento actual.
     * @return Var value - Valor del elemento.
     */    
	public function getValue()
	{
		return $this->_value;
	}
        
	/**
	 * Define el elemento padre.
	 * @param OXmlElement $element - Elemento.
	 */
	public function setParentElement( OXmlElement $element )
	{
		$this->_parent_element = $element;
	}
        
	/**
	 * Devuelve el elemento padre.
	 * @return OXmlElement - Elemento padre.
	 */
	public function getParentElement()
	{
		return $this->_parent_element;
	}
	
	/**
	 * Define el valor del id del elemento actual.
	 * @param Var $id
	 */
	public function setId($id)
	{
		if( !$this->addAttribute( new OXmlAttribute( 'id' , $id ) ) )
			$this->getAttribute('id')->setValue($id);
	}
	
	/**
	 * Devuelve el valor del id del elemento actual.
	 * @return Var value. Valor del Id.
	 */
	public function getId()
	{
		return $this->getAttribute('id')->getValue();
	}
	
	/**
	 * Devuelve el elemento hijo segun el id.
	 * @param Var $id - id del elemento.
	 * @return OXmlElement - Elemento hijo.
	 */
	public function getChildElementById($id)
	{
		foreach ( $this->getAllChildElements() as $element ) 
		{
			if( $element->getAttribute('id')->getValue() == $id )
				return $element;
		}
		return false;
	}
}
?>